package com.poi.java.util;

import com.poi.java.controller.WordController;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDrawing;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.springframework.http.ResponseEntity;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;

import static org.springframework.core.io.buffer.DataBufferUtils.readInputStream;

public class WordUtils {

	public static String allwrite(String inputSrc, String outSrc, Map<String,String> map) {
        try {
        	//判断文件是否存在
			File file = new File(inputSrc);
			if(!file.exists()){
				System.err.println("文件不存在");
				return "fail";
			}else {

	            //得到.docx文件提取器
//	            XWPFDocument doc = new XWPFDocument(POIXMLDocument.openPackage(inputSrc));
				CustomXWPFDocument doc = new CustomXWPFDocument(POIXMLDocument.openPackage(inputSrc));//


				//duand
//				doParagraphs(doc);

				/**
                 * 替换段落中指定的文本
                 */

				replaceWordText(doc.getParagraphs(),map);
	            for(XWPFParagraph p : doc.getParagraphs()){
	                List<XWPFRun> runs = p.getRuns();

	                if(runs != null){
						for(XWPFRun r : runs){
//	                        //需要替换的文本
	                        String text = r.getText(0);
							System.out.println(text);}
						boolean daxieFlag = false;
//	                    for(XWPFRun r : runs){
//	                        //需要替换的文本
//	                        String text = r.getText(0);
//							System.out.println(text);
//
//							List<CTDrawing> drawings = getAllDrawings(r);
//							for (CTDrawing drawing:drawings){
//								if (drawing.xmlText().contains("#case_etc#")){
//									FileInputStream is = new FileInputStream("D:\\p1.jpg");
//									r.addAnchorPicture(is,XWPFDocument.PICTURE_TYPE_JPEG,"p1.jpg",Units.toEMU(430),Units.toEMU(280));
////									String picId = doc.addPictureData(is, XWPFDocument.PICTURE_TYPE_JPEG);
////									doc.addPictureRewrite(r,picId,XWPFDocument.PICTURE_TYPE_JPEG, 600, 400);
//									is.close();
//								}
//							}
//
//	                        //替换指定的文本
////	                        for(String key : map.keySet()){
//	                            if((text != null && map.get(text.trim())!=null) ||"汉字".equals(text) || (text != null &&text.contains("#"))){
//	                                //替换的时候要注意，setText是有两个参数的
//	                                //第一个是替换的文本，第二个是从哪里开始替换
//	                                //0是替换全部，如果不设置那么默认就是从原文字
//	                                //结尾开始追加
//
//									//容错 比如 #sr_des#,#src_des#
//									if (text.indexOf(",")>0){
//										String[] t = text.split(",");
//										for (int j =0;j<t.length;j++){
//											r.setText(map.get(t[j].trim()),0);
//										}
//									}
//
//									if (text.equals("汉字")){
//										r.setText("",0);
//										daxieFlag = true;
//									}else if (daxieFlag){
//										r.setText(ToChUtils.toCh(map.get(text.trim())),0);
//										daxieFlag=false;
//									}else {
//										r.setText(map.get(text.trim()),0);
//									}
////	                            }
//	                        }
//	                    }
	                }
	            }


	            for(XWPFTable tab : doc.getTables()){
	                for(XWPFTableRow row : tab.getRows()){
	                    for(XWPFTableCell cell : row.getTableCells()){
	                        //注意，getParagraphs一定不能漏掉
	                        //因为一个表格里面可能会有多个需要替换的文字
	                        //如果没有这个步骤那么文字会替换不了
							replaceWordText(cell.getParagraphs(),map);
//	                        for(XWPFParagraph p : cell.getParagraphs()){
//	                            for(XWPFRun r : p.getRuns()){
//	                                String text = r.getText(0);
//
//									System.out.println(text);
//									if (text != null && map.get(text.trim())!=null || (text != null &&text.contains("#"))){
//										//容错 比如 #sr_des#,#src_des#
//										if (text.indexOf(",")>0){
//											String[] t = text.split(",");
//											for (int j =0;j<t.length;j++){
//												r.setText(map.get(t[j].trim()),0);
//											}
//										}
//										r.setText(map.get(text.trim()),0);
//									}
//
//	                            }
//	                        }
	                    }
	                }
	            }

				for ( XWPFFooter footer:doc.getFooterList()){
						for (XWPFParagraph paragraph:footer.getListParagraph()){
							List<XWPFRun> runs = paragraph.getRuns();
							if(runs != null){
								for(XWPFRun r : runs){
									String text = r.getText(0);
//									System.out.println(text);
									if (text != null && map.get(text.trim())!=null){
										r.setText(map.get(text.trim()),0);
									}

									if (text != null && text.contains("#")&&map.get(text.trim())==null){
										//容错 比如 报告编号：#ReportCodeTec
										if (text.indexOf("#")>0){
											String[] t = text.split("#");
											for (int j =0;j<t.length;j++){
												if (map.get(t[j].trim()) !=null){
													r.setText(map.get(t[j].trim()),0);
												}
											}
										}
									}


								}
							}
						}
				}


//

//				File file1 = new File("D:\\p1.jpg");
//				FileInputStream iss = new FileInputStream(file1);
//				String picId = doc.addPictureData(iss, XWPFDocument.PICTURE_TYPE_JPEG);
//				doc.addPictureRewrite(run,picId,XWPFDocument.PICTURE_TYPE_JPEG, 450, 300);

				replaceImg(doc, "rId3");//替换
	            doc.write(new FileOutputStream(outSrc));

	            return "succ";
			}
        } catch (IOException e) {
            e.printStackTrace();
            return "succ";
        } catch (Exception e) {
			throw new RuntimeException(e);
		}
	}


	//替换word中的占位符
	private static void replaceWordText(List<XWPFParagraph> paragraphList, Map<String, String> param) {
		for (XWPFParagraph paragraph : paragraphList) {
			// 遍历获取段落中所有的runs
			List<XWPFRun> runs = paragraph.getRuns();
			// 合并逻辑
			for (int i = 0; i < runs.size(); i++) {
				//获取字符
				String text0 = runs.get(i).getText(runs.get(i).getTextPosition());
				System.out.println(text0);
				if (text0 != null && text0.contains("#")) {
					//包含占位符的字符缓存
					StringBuilder cache = new StringBuilder(text0);
					//记录run结束的角标，开始的角标为i
					int endIndex = 0;
					boolean contains = text0.contains("#");
					//同一个run中是否包含完成占位符
					if (!contains) {
						int j = i + 1 ;
						for (; j < runs.size(); j++) {
							String text1 = runs.get(j).getText(runs.get(j).getTextPosition());
							if (text1 == null) {
								continue;
							}
							cache.append(text1);
							if (text1.contains("#")) {
								endIndex = j;
								break;
							}
						}
					}
					if (contains || endIndex != 0) {
						//处理替换
						String s = cache.toString();

						if (param.get(s) ==null && !s.contains("/")){
							param.put(s,"");
						}

						for (Map.Entry<String, String> entry : param.entrySet()) {
							String k = entry.getKey();
							String v = entry.getValue().toString();
							if (s.contains(k)) {
//								log.info("替换字符串：{} -> {}", k, v);
								System.err.println("替换字符串：{} -> {}k:"+ k+",v:"+ v);
								String replace = s.replace(k, v);
								if (replace.contains("#")){
									s = replace;
								}else {
									runs.get(i).setText(replace, 0);
									for (int j = endIndex; j > i; j--) {
										//角标移除后，runs会同步变动，直接继续处理i就可以
//										log.info("移除下标：{}", j);
										System.err.println("移除下标：{}"+ j);
										paragraph.removeRun(j);
									}
									break;
								}

							}
						}
					}
				}
			}
		}
	}



	/**
	 * 将文件url转成字节数组
	 * @param url
	 * @return
	 */
	private static byte[] getFileStream(String url){
		try {
			URL httpUrl = new URL(url);
			HttpURLConnection conn = (HttpURLConnection)httpUrl.openConnection();
			conn.setRequestMethod("GET");
			conn.setConnectTimeout(5 * 1000);
			InputStream inStream = conn.getInputStream();//通过输入流获取图片数据
			byte[] btImg = readInputStream(inStream);//得到图片的二进制数据
			return btImg;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private static InputStream getImageStream(String url) {
		try {
			HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
			connection.setReadTimeout(5000);
			connection.setConnectTimeout(5000);
			connection.setRequestMethod("GET");
			if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
				InputStream inputStream = connection.getInputStream();
				return inputStream;
			}
		} catch (IOException e) {
//			log.info("获取网络图片出现异常，图片路径为：" + url);
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 从输入流中获取数据
	 * @param inStream 输入流
	 * @return
	 * @throws Exception
	 */
	private static byte[] readInputStream(InputStream inStream) throws Exception{
		ByteArrayOutputStream outStream = new ByteArrayOutputStream();
		byte[] buffer = new byte[1024];
		int len = 0;
		while( (len=inStream.read(buffer)) != -1 ){
			outStream.write(buffer, 0, len);
		}
		inStream.close();

		return outStream.toByteArray();
	}


	public static void main(String[] args) throws IOException {

		HashMap<String, String> map = new HashMap<>();
		map.put("${year3}","2014");
		map.put("${year2","2013");
		String srcPath = "D:\\project\\poi\\java\\src\\main\\resources\\word\\tes.docx";   //模板文件的地址
		String destPath = "D:\\temp\\1_tt.docx"; //替换后保存的地址
		WordUtils.allwrite(srcPath,destPath,map);
//		InputStream in = new FileInputStream(srcPath);
//		XWPFDocument xwpfDocument = new XWPFDocument(in);
//		List<XWPFParagraph> paragraphList = xwpfDocument.getParagraphs();
//		System.out.println("图片的索引	|图片名称	|图片上一段文字的内容	");
//		System.out.println("------------------------------------------");
//		for(int i = 0;i < paragraphList.size();i++){
//			List<String> imageBundleList = XWPFUtils.readImageInParagraph(paragraphList.get(i));
//			if(CollectionUtils.isNotEmpty(imageBundleList)){
//				for(String pictureId:imageBundleList){
//					XWPFPictureData pictureData = xwpfDocument.getPictureDataByID(pictureId);
//					String lastParagraphText = paragraphList.get(i-1).getParagraphText();
//					String imageName = pictureData.getFileName();
//					System.err.println(pictureId +"	|" + imageName + "	|" + lastParagraphText);
//				}
//			}
//		}
	}

	private static List<CTDrawing> getAllDrawings(XWPFRun run) throws Exception {
		CTR ctR = run.getCTR();
		XmlCursor cursor = ctR.newCursor();
		cursor.selectPath("declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' .//*/w:drawing");
		List<CTDrawing> drawings = new ArrayList<CTDrawing>();
		while (cursor.hasNextSelection()) {
			cursor.toNextSelection();
			XmlObject obj = cursor.getObject();
			CTDrawing drawing = CTDrawing.Factory.parse(obj.newInputStream());
			drawings.add(drawing);
		}
		return drawings;
	}


	public static void replaceImg(XWPFDocument document, String rid) {
		byte[] ba = getFileStream("http://www.baidu.com/img/bdlogo.png");
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(ba);
//		ByteArrayInputStream byteArrayInputStream = getBase64Input(base64);
		String ind = "";
		//已经改好了不用动了。
		try {
			document.getPackagePart().removeRelationship(rid);//删除原有印章

			ind = document.addPictureData(byteArrayInputStream,XWPFDocument.PICTURE_TYPE_PNG);//在word插入一张没有关系的图片数据
			//将新插入的图片关系替换到模板图片上，替换的只是图片数据，大小位置还是原来模板的
			document.getPackagePart().addRelationship(document.getPackagePart().
							getRelationship(ind).getTargetURI(), TargetMode.INTERNAL,
					XWPFRelation.IMAGES.getRelation(), rid);
		} catch (InvalidFormatException e) {
			e.printStackTrace();
//			throw new BizException("替换图片失败");
		}
	}



}
